import {defineStore} from "pinia";
import dayjs from "@/utils/dayjs";
import {EventStreamContentType, fetchEventSource} from "@microsoft/fetch-event-source";

export const useAiStore = defineStore('ai', {
    persist: true, //使用持久化插件
    state: () => {   //是一个函数，返回一个对象，用于存储状态
        return {
            sessionList: [] as IAiSession[],
            curSession: {} as IAiSession,
            takeMessageNum: 7,
            apiKey: ''

        }
    },
    getters: {
        curSessionIsFirst(state) {
            return (state.sessionList.length && state.sessionList[0].id === state.curSession.id) || state.sessionList.length === 0
        },
        curSessionIsLast(state) {
            return (state.sessionList.length && state.sessionList[state.sessionList.length - 1].id === state.curSession.id) || state.sessionList.length === 0
        }

    },  //用于存储计算属性
    actions: {  //用于封装业务逻辑
        createNewSession(username: string) {
            //@ts-ignore
            if (this.sessionList && this.sessionList.length && this.sessionList.at(0).messages.length === 1) {
                this.curSession = this.sessionList.at(0) || {} as IAiSession
                return
            }
            const item: IAiSession = {
                id: dayjs().unix(),
                title: '新的会话',
                createdAt: dayjs().format('YYYY-MM-DD HH:mm'),
                messages: [
                    {
                        role: 'assistant',
                        content: '有什么可以帮你的吗',
                        createdAt: dayjs().format('YYYY-MM-DD HH:mm'),
                    },
                ],
                username: username,
                systemHistorySummary: '',
                isReplying: false,
                ctrl: new AbortController(),
            }
            this.curSession = item
            this.sessionList.unshift(item)
        },
        removeSession(item: IAiSession) {
            if (item.id === this.curSession.id) {
                this.curSession = {} as IAiSession
            }
            const index = this.sessionList.indexOf(item)
            this.sessionList.splice(index, 1)
        },
        sendMessage(content: string) {
            this.curSession.messages.push({
                role: 'user',
                content: content,
                createdAt: dayjs().format('YYYY-MM-DD HH:mm'),
            }, {
                role: 'assistant',
                content: '稍等，正在思考中...',
                createdAt: dayjs().format('YYYY-MM-DD HH:mm'),
            })
            let lastAiMessageIndex = this.curSession.messages.length - 1
            this.handleCompletions(this.curSession, lastAiMessageIndex)
        },
        stopReply() {
            this.curSession.ctrl.abort()
            this.curSession.isReplying = false
        },
        switchSession(direction: 'prev' | 'next') {
            let index = this.sessionList.findIndex(item => item.id === this.curSession.id)
            if (direction === 'prev') {
                index === 0 ? index = 0 : index--
            } else {
                index === this.sessionList.length - 1 ? index = this.sessionList.length - 1 : index++
            }
            this.curSession = this.sessionList[index]
        },
        handleMessageFormat(session: IAiSession) {
            let messages = session.messages.slice(-this.takeMessageNum)
            let messageRes: IAiMessage[] = [{
                role: 'system',
                content: `\n` +
                    'You are ChatGPT, a large language model trained by OpenAI.\n' +
                    'Knowledge cutoff: 2021-09\n' +
                    'Current model: gpt-3.5-turbo\n' +
                    `Current time: ${dayjs().format('YYYY-MM-DD HH:mm')}\n`,
            },]
            if (session.systemHistorySummary) {
                messageRes.push({
                    content: session.systemHistorySummary,
                    role: 'system',
                })
            }
            messages.forEach((item) => {
                messageRes.push({
                    content: item.content,
                    role: item.role === 'assistant' ? 'assistant' : 'user',
                })
            })
            return messageRes
        },
        handleCompletions(session: IAiSession, lastAiMessageIndex: number) {
            const _this = this
            const body = {
                "messages": this.handleMessageFormat(session),
                "stream": true,
                "model": "gpt-3.5-turbo",
                "temperature": 1,
                "presence_penalty": 0
            }
            session.ctrl = new AbortController();
            fetchEventSource('/ChatGPT', {
                method: 'POST',
                headers: {
                    'content-type': 'application/json',
                    'Authorization': 'Bearer ' + (this.apiKey ? this.apiKey : 'nk-zzj314314'),
                },
                body: JSON.stringify(body),
                signal: session.ctrl.signal,
                openWhenHidden: true,
                async onopen(response) {
                    if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
                        session.isReplying = true
                        //@ts-ignore
                        session.messages.at(lastAiMessageIndex).content = ''
                    } else if (response.status === 429 || response.status === 401) {
                        //@ts-ignore
                        session.messages.at(lastAiMessageIndex).content = response.statusText
                        window.$message.warning(response.statusText)
                    }
                },
                onmessage(ev) {
                    if (ev.data === "[DONE]") {

                    } else {
                        let json = JSON.parse(ev.data);
                        let str = json.choices[0].delta.content
                        if (str) {
                            //@ts-ignore
                            session.messages.at(lastAiMessageIndex).content += str
                        }
                    }

                },
                onclose() {
                    console.log(JSON.stringify(session.messages).length)
                    session.isReplying = false
                    if ((session.messages.length >= 7 || (session.messages.length >= 3 && JSON.stringify(session.messages).length > 500)) && session.title === '新的会话') {
                        _this.handleTitle(session)
                    }
                    if ((session.messages.length - 1) % (_this.takeMessageNum - 1) === 0 && JSON.stringify(session.messages).length > 500) {
                        _this.handleSummary(session)
                    }
                    // if (session.messages.length > 7 && JSON.stringify(session.messages).length > 1000 && !session.systemHistorySummary) {
                    //     _this.handleSummary(session)
                    // }
                },
                onerror(err) {
                    console.log('err')
                    throw err;
                }
            })
        },

        handleTitle(session: IAiSession) {
            let messageRes: IAiMessage[] = []
            session.messages.forEach((item) => {
                messageRes.push({
                    content: item.content,
                    role: item.role === 'assistant' ? 'assistant' : 'user',
                })
            })
            messageRes.push({
                content: '使用四到五个字直接返回这句话的简要主题，不要解释、不要标点、不要语气词、不要多余文本，如果没有主题，请直接返回“闲聊”',
                role: 'user',
            })
            const body = {
                "messages": messageRes,
                "stream": true,
                "model": "gpt-3.5-turbo",
                "temperature": 1,
                "presence_penalty": 0
            }
            fetchEventSource('/ChatGPT', {
                method: 'POST',
                headers: {
                    'content-type': 'application/json',
                    'Authorization': 'Bearer ' + (this.apiKey ? this.apiKey : 'nk-zzj314314'),
                },
                body: JSON.stringify(body),
                openWhenHidden: true,
                async onopen(response) {
                    if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
                        session.title = ''
                    } else if (response.status === 429) {

                    }
                },
                onmessage(ev) {
                    if (ev.data === "[DONE]") {

                    } else {
                        let json = JSON.parse(ev.data);
                        let str = json.choices[0].delta.content
                        if (str) {
                            session.title += str
                        }
                    }
                },
                onclose() {
                },
                onerror(err) {
                    throw err;
                }
            })
        },
        handleSummary(session: IAiSession) {
            let messageRes: IAiMessage[] = []
            if (session.systemHistorySummary) {
                messageRes.push({
                    content: session.systemHistorySummary,
                    role: 'system',
                })
            }
            session.messages.slice(-this.takeMessageNum).forEach((item) => {
                messageRes.push({
                    content: item.content,
                    role: item.role === 'assistant' ? 'assistant' : 'user',
                })
            })
            messageRes.push({
                content: '简要总结一下对话内容，用作后续的上下文提示 prompt，控制在 200 字以内',
                role: 'system',
            })
            const body = {
                "messages": messageRes,
                "stream": true,
                "model": "gpt-3.5-turbo",
                "temperature": 1,
                "presence_penalty": 0
            }
            fetchEventSource('/ChatGPT', {
                method: 'POST',
                headers: {
                    'content-type': 'application/json',
                    'Authorization': 'Bearer ' + (this.apiKey ? this.apiKey : 'nk-zzj314314'),
                },
                body: JSON.stringify(body),
                openWhenHidden: true,
                async onopen(response) {
                    if (response.ok && response.headers.get('content-type') === EventStreamContentType) {

                    } else if (response.status === 429) {

                    }
                },
                onmessage(ev) {
                    if (ev.data === "[DONE]") {

                    } else {
                        let json = JSON.parse(ev.data);
                        let str = json.choices[0].delta.content
                        if (str) {
                            session.systemHistorySummary += str
                        }
                    }
                },
                onclose() {
                },
                onerror(err) {
                    throw err;
                }
            })
        }

    },
})
